﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.DirectoryServices.Protocols;
using System.Text;
using System.Text.RegularExpressions;
using VPLink2013.Framework;

namespace VPLink2013.Batch
{
    public class LDAPManager
    {
        private LdapConnection _ldapConnection;
        private Dictionary<string, string> dicLoginPicUrl;
        private Dictionary<string, string> dicLoginSitePerso;
        private List<string> managers;
        public LDAPManager(string serverName, int portNumber, string vplinkUrl, string picLibUrl, string myVPLinkUrl, string extraLdapFilter)
        {
            _ldapConnection = new LdapConnection(new LdapDirectoryIdentifier(serverName, portNumber));
            _ldapConnection.AuthType = AuthType.Anonymous;
            _ldapConnection.Bind();

            dicLoginPicUrl = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
            dicLoginSitePerso = new Dictionary<string, string>();
            EmployeeExtraInfo d = new EmployeeExtraInfo(vplinkUrl, picLibUrl, myVPLinkUrl);

            d.EmployeesLoginsExtraInfoDicos(dicLoginPicUrl, dicLoginSitePerso);

            string sFilter = String.Format("(&(cn=*)(|(ixstatus=DEPARTUR*)(ixstatus=NEW)){0})", extraLdapFilter);

            SearchRequest request = new SearchRequest("ou=People,dc=ilex-si,dc=eu", sFilter, System.DirectoryServices.Protocols.SearchScope.OneLevel);
            request.Attributes.Add(Constants.ManagerCodeLDAPField);
            request.Attributes.Add(Constants.CommonNameDAPField);
            SearchResponse response = (SearchResponse)_ldapConnection.SendRequest(request);
            managers = response.Entries.Cast<SearchResultEntry>()
                .Select(x => x.AttributeValueAsString(Constants.ManagerCodeLDAPField)).Distinct().ToList();
        }
        public Employee GetEmployeeByValue(string value, string extraLdapFilter)
        {
            string sFilter = String.Format("(&(cn={0})(|(ixstatus=DEPARTUR*)(ixstatus=NEW)){1})", value, extraLdapFilter);

            SearchRequest request = new SearchRequest("ou=People,dc=ilex-si,dc=eu", sFilter, System.DirectoryServices.Protocols.SearchScope.OneLevel);
            AddNeededAttributes(request);

            SearchResponse response = (SearchResponse)_ldapConnection.SendRequest(request);
            if (response != null)
            {
                if (response.Entries.Count == 1)
                {
                    Employee emp = new Employee(response.Entries[0]);
                    SetEmployeeExtraInfo(emp);
                    return emp;
                }
                else
                {
                    return null;
                }
            }
            else
            {
                return null;
            }
        }
        public List<Employee> GetEmployeesByOUCode(List<string> ouCodes, string siteUrl, string picLibUrl, string extraLdapFilter)
        {
            StringBuilder sbFilter = new StringBuilder();

            ouCodes.ForEach(x => sbFilter.AppendFormat("(ixoucodecache={0}{1})",
                Constants.LDAP_Init_Prefix,
                string.Join("*-*", x.Split('-').Select(y => Regex.Replace(y.Trim(), @"\s+", "*")).ToArray())));

            string sFilter = String.Format("(&(cn=*)(|(ixstatus=DEPARTUR*)(ixstatus=NEW)){0}(|{1}))", extraLdapFilter, sbFilter.ToString());
            SearchRequest request = new SearchRequest("ou=People,dc=ilex-si,dc=eu", sFilter, System.DirectoryServices.Protocols.SearchScope.OneLevel);

            AddNeededAttributes(request);
            SearchResponse response = (SearchResponse)_ldapConnection.SendRequest(request);

            List<string> values = response.Entries.Cast<SearchResultEntry>()
                .Select(x => x.AttributeValueAsString(Constants.CommonNameDAPField))
                .Distinct().ToList();
            List<Employee> sceEmployees = new List<Employee>();
            foreach (SearchResultEntry sr in response.Entries)
            {
                Employee emp = new Employee(sr);
                if (dicLoginPicUrl.ContainsKey(emp.Login))
                {
                    SetEmployeeExtraInfo(emp);
                    ContextTrace.AddTrace(string.Format("Login : {0} ; IsManager : {1} ; SitePerso : {2}", emp.Login, emp.IsManager, emp.SitePersonnel));
                    sceEmployees.Add(emp);
                    //yield return emp;
                }
                else
                {
                    ContextTrace.AddTrace(string.Format("Login {0} n'a pas été trouvé dans le dictionnaire", emp.Login));
                }
            }
            return sceEmployees;
        }

        private void SetEmployeeExtraInfo(Employee emp)
        {
            emp.PictureUrl = dicLoginPicUrl.ContainsKey(emp.Login) ? dicLoginPicUrl[emp.Login] : string.Empty;
            emp.SitePersonnel = dicLoginSitePerso.ContainsKey(emp.Login) ? dicLoginSitePerso[emp.Login] : string.Empty;
            emp.IsManager = managers.Contains(emp.Value);
        }

        private static void AddNeededAttributes(SearchRequest request)
        {
            request.Attributes.Add(Constants.DisaplayNameLDAPField);
            request.Attributes.Add(Constants.ValueLDAPField);
            request.Attributes.Add(Constants.LastNameLDAPField);
            request.Attributes.Add(Constants.FirstNameLDAPField);
            request.Attributes.Add(Constants.ManagerNameLDAPField);
            request.Attributes.Add(Constants.ManagerCodeLDAPField);
            request.Attributes.Add(Constants.OUDispalyNameLDAPField);
            request.Attributes.Add(Constants.OUCodeLDAPField);
            request.Attributes.Add(Constants.eMailLDAPField);
            request.Attributes.Add(Constants.EmptyIfNotManagerLDAPField);
            request.Attributes.Add(Constants.TelephoneNumberDAPField);
            request.Attributes.Add(Constants.TitleLDAPField);
            request.Attributes.Add(Constants.CommonNameDAPField);
        }
    }
}
